# _*_ coding:utf-8 _*_
# @Time  : 2023.04.04
# @Author: zizlee

""" 陪同走访 """
import pathlib
import datetime
from fastapi import APIRouter, Header, Body, Query, BackgroundTasks, Form, UploadFile
from pydantic import BaseModel, constr, validator

from hutool import security
from v1_all_api.all_utils import datetime_utils, file_utils
from v1_all_api.all_response import AllResponse
from db import FAConnection
from configs import STATIC_FILE_HOST, FILE_STORAGE
from logger import logger

from . import handler_utils

accompany_api = APIRouter()

MODULE_NAME = 'Accompany'
SPECIAL_WORK_TAG = 'T03'
# ---------------------------------- 函数任务 ---------------------


# 记录任务，添加到非常态工作记录中
def add_work_record(rid):
    print('添加非常规工作', rid)
    insert_sql = """
        INSERT INTO work_special_task (user_id,create_date,title,task_type,sponsor,applicant,phone,
        swiss_coin,allowance,partner,note,score,annex,annex_url,prse_id,prse_module)
        VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);
    """
    with FAConnection() as cursor:
        # 查询该ID的记录信息
        cursor.execute("""
            SELECT a.*,u.admin_name FROM prse_accompany_visit As a INNER JOIN ruizy_user As u ON a.creator=u.id WHERE a.id=%s LIMIT 1;
        """, [rid])
        obj = cursor.fetchone()
        if not obj:
            return False
        # 查询该ID是否被添加进了记录
        cursor.execute('SELECT id FROM work_special_task WHERE prse_id=%s AND prse_module=%s LIMIT 1;', [rid, MODULE_NAME])
        task_obj = cursor.fetchone()
        if task_obj:  # 更新记录
            update_prm = [obj['evaluate'], obj['annex_name'], obj['annex'], task_obj['id']]
            uc = cursor.execute('UPDATE work_special_task SET score=%s,annex=%s,annex_url=%s WHERE id=%s LIMIT 1;', update_prm)
            if uc < 1:
                logger.warning('疑似更新work_special_task评分结果出错，更新数: {}'.format(uc))
        else:  # 添加记录
            create_date = obj['annex_time'].strftime('%Y%m%d')
            score = obj['evaluate'] if obj['evaluate'] else 0
            insert_prm = [obj['worker_id'], create_date, obj['visit_to'], SPECIAL_WORK_TAG, '', obj['admin_name'],
                          obj['link_msg'], obj['quota'], 0, '', '', score, obj['annex_name'], obj['annex'], rid, MODULE_NAME]
            ic = cursor.execute(insert_sql, insert_prm)
            if ic < 1:
                logger.warning('疑似插入work_special_task记录结果出错，插入数: {}'.format(ic))
            print('添加work_special_task完成')
    return True


# ---------------------------------------------------- 前端申请等 -------------------------------------------------------


class AccompanyItem(BaseModel):
    visit_time: str
    visit_site: constr(max_length=300)
    visit_to: constr(max_length=300)
    content: constr(max_length=500)
    link_msg: constr(max_length=300)

    @validator('visit_time')
    def validate_lecture_time(cls, value):
        dt = datetime_utils.auth_datetime_string(value, f='%Y-%m-%d %H:%M:%S')
        if not dt:
            raise ValueError('日期格式错误,接受%Y-%m-%d %H:%M:%S型.')
        return dt


# 评价陪同走访的项目
class AccompanyEvaluateItem(BaseModel):
    id: int
    evaluate: int
    evaluate_plain: str
    is_anonymous: bool


# 申请者提交一个陪同走访申请
@accompany_api.post('/my/')
def create_accompany_visit(ruizy_token: str = Header(...), visit: AccompanyItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否够申请积分
    need_quota, remain_quota = handler_utils.quota_information(module_name=MODULE_NAME, user_id=person['uid'])
    if need_quota > remain_quota:
        return AllResponse.validate_error(msg='申请所需积分为: {}，当前剩余：{}。'.format(need_quota, remain_quota))
    # 将数据保存
    sql = """
      INSERT INTO prse_accompany_visit(creator,visit_time,visit_site,visit_to,content,link_msg,state,quota)
      VALUES (%s,%s,%s,%s,%s,%s,%s,%s);
    """
    prm = (person['uid'], visit.visit_time, visit.visit_site, visit.visit_to, visit.content, visit.link_msg, 0, need_quota)
    with FAConnection() as cursor:
        c = cursor.execute(sql, prm)
        if c:
            cursor.execute('SELECT LAST_INSERT_ID() AS insertID;')
            insert_id = cursor.fetchone()['insertID']
            # 申请成功，扣取积分
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=insert_id, cursor=cursor,
                                           change=need_quota, module_key=MODULE_NAME)
    return AllResponse.create_successfully(msg='提交成功，请前往记录查看.') if c else AllResponse.server_error()


@accompany_api.get('/my/')
def query_my_accompany_visit(ruizy_token: str = Header(...),
                             page: int = Query(...), page_size: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询自己的申请记录
    sql = """
      SELECT * FROM prse_accompany_visit WHERE creator=%s ORDER BY create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [person['uid']], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待中',
        1: '进行中',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['visit_time'] = datetime_utils.to_string(row['visit_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        row['annex_public'] = True if row['annex_public'] else False
        if row['annex'] and row['annex_public']:
            row['has_annex'] = True
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
        else:
            row['annex_url'] = ''
            row['annex_name'] = '无'
            row['has_annex'] = False
        del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 对一个申请结果评价
@accompany_api.post('/myEvaluate/')
def evaluate_accompany_visit(ruizy_token: str = Header(...), evaluate: AccompanyEvaluateItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否评价过了
    sql = """
      UPDATE prse_accompany_visit SET evaluate=%s,evaluate_plain=%s,is_anonymous=%s WHERE id=%s AND creator=%s LIMIT 1;
    """
    prm = (evaluate.evaluate, evaluate.evaluate_plain, evaluate.is_anonymous, evaluate.id, person['uid'])
    with FAConnection() as cursor:
        cursor.execute('SELECT id,evaluate,annex_name,annex,annex_public FROM prse_accompany_visit WHERE id=%s AND creator=%s LIMIT 1;',
                       (evaluate.id, person['uid']))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.no_do_anything(msg='未检测到该条数据，评价失败.')
        if obj['evaluate'] and obj['evaluate'] > 0:
            return AllResponse.validate_error(msg='您已经评价过，无需重复评价.')
        cursor.execute(sql, prm)
    add_work_record(evaluate.id)
    # 返回附件地址
    annex_url = ''
    if obj['annex'] and obj['annex_public']:
        annex_url = STATIC_FILE_HOST + obj['annex']
    return AllResponse.operate_successfully(msg='评价成功', data={
        'evaluate': evaluate.evaluate, 'id': evaluate.id, 'annex_url': annex_url,
        'has_annex': True if annex_url else False
    })


# 预览材料文件
@accompany_api.get('/my/dataPreView/')
def preview_accompany_visit(ruizy_token: str = Header(...), rid: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询数据资料
    with FAConnection() as cursor:
        cursor.execute('SELECT id,visit_to,annex FROM prse_accompany_visit WHERE id=%s LIMIT 1;', (rid, ))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.server_no_content(msg='数据不存在')
    if not obj['annex']:
        return AllResponse.validate_error('还没有资料文件')
    # 资料文件
    annex_file = pathlib.Path(FILE_STORAGE).joinpath(obj['annex'])
    if not annex_file.exists():
        return AllResponse.server_no_content(msg='数据资料不存在')
    # 读取预览图片文件
    preview_folder = annex_file.parent.joinpath(annex_file.name + 'img')
    if preview_folder.exists() and not preview_folder.is_file():
        # 存在着预览的图片文件，读取文件信息
        if annex_file.name.endswith('.ppt') or annex_file.name.endswith('.pptx'):
            images = file_utils.get_file_list(preview_folder, glob='*.jpg', replaces=['幻灯片', '.JPG'])
        else:
            images = file_utils.get_file_list(preview_folder, glob='*.png')
    else:
        # 不存在，就得转化
        images = handler_utils.covert_file2image(annex_file)
        if len(images) < 1:
            return AllResponse.validate_error(msg='不支持预览的资料')
    images = [str(i).replace('\\', '/').replace(FILE_STORAGE, STATIC_FILE_HOST) for i in images]
    return AllResponse.operate_successfully(data={
        'id': rid,
        'topic': obj['visit_to'],
        'images': images
    })


# ---------------------------------------------------- 管理员处理 -------------------------------------------------------


# 管理员查询
@accompany_api.get('/manage/')
def query_accompany_visit(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    sql = """
        SELECT a.*,u.admin_name FROM prse_accompany_visit As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待',
        1: '通过',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['visit_time'] = datetime_utils.to_string(row['visit_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)


class DispatchModel(BaseModel):
    rid: int
    worker_id: int
    state: int
    explain_state: str


# 管理员分配任务
@accompany_api.post('/manage/')
def dispatch_accompany_visit(ruizy_token: str = Header(...), dispatch_item: DispatchModel = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    sql = "UPDATE prse_accompany_visit SET state=%s,state_plain=%s,worker_id=%s,dispatch_time=%s WHERE id=%s LIMIT 1;"
    prm = [dispatch_item.state, dispatch_item.explain_state, dispatch_item.worker_id, now_time, dispatch_item.rid]
    with FAConnection() as cursor:
        cursor.execute('SELECT id,quota FROM prse_accompany_visit WHERE id=%s LIMIT 1;', [dispatch_item.rid])
        _obj = cursor.fetchone()
        if not _obj:
            return AllResponse.validate_error(msg='处理的记录不存在!')
        cursor.execute(sql, prm)  # 执行分配
        if dispatch_item.state == -1:  # 拒绝记录
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=dispatch_item.rid, cursor=cursor,
                                           change=-_obj['quota'], module_key=MODULE_NAME)

    return AllResponse.operate_successfully(msg='处理申请记录成功!')


# 将任务手动添加到【非常规工作中】中
@accompany_api.post('/manage/addSpecialWork/')
def active_add_special_work(ruizy_token: str = Header(...), rid: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    # 添加一条路演记录，类型和规模按line和scale字段名内外培训。此功能在相关任务人员上传材料时也有实现
    success = add_work_record(rid)
    msg = '添加非常规工作记录成功！' if success else '记录不存在,添加失败!'
    return AllResponse.operate_successfully(msg=msg)

# ---------------------------------------------------- 任务员处理 -------------------------------------------------------


# 人员查询自己的任务
@accompany_api.get('/worker/')
def query_accompany_visit_tome(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    sql = """
        SELECT a.*,u.admin_name FROM prse_accompany_visit As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s AND a.worker_id=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state, person['uid']], page=page, page_size=page_size)
    states = {
        1: '待处理',
        2: '已完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['visit_time'] = datetime_utils.to_string(row['visit_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 人员上传附件材料或完成走访
@accompany_api.post('/worker/')
async def finish_lecture_train_tome(bg_tasks: BackgroundTasks, ruizy_token: str = Header(...),
                                    rid: int = Form(...), annex_public: bool = Form(False), annex: UploadFile = Form(None)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if annex:
        # 写入文件
        save_path, sql_path = file_utils.get_file_paths(module_name='ProductService/AccompanyVisit', filename=annex.filename,
                                                        hashed=True)
        annex_content = await annex.read()
        with open(save_path, 'wb') as fp:
            fp.write(annex_content)
        annex_name = annex.filename
    else:
        save_path = ''
        sql_path = ''
        annex_name = ''
    # 更新数据
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    annex_public = 1 if annex_public else 0
    sql = "UPDATE prse_accompany_visit SET annex_name=%s,annex_time=%s,annex=%s,annex_public=%s,state=2 WHERE id=%s LIMIT 1;"
    prm = [annex_name, now_time, sql_path, annex_public, rid]
    with FAConnection() as cursor:
        cursor.execute(sql, prm)
    # 添加非常态工作记录
    bg_tasks.add_task(add_work_record, rid)
    if annex and save_path:
        bg_tasks.add_task(handler_utils.covert_file2image, pathlib.Path(save_path))  # 后台任务转为图片
    return AllResponse.operate_successfully(msg='陪同走访完成!')
